package com.googlecode.likesql.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;



/**
 * This class is to manipulate string(s).
 * 
 * @author Johny Huang
 * @since 0.1
 * @see {@link String}
 *
 */
public final class StringUtils {

    public final static String EMPTY="";
    
    public final static String WHITESPACE=" ";
    
    public final static String NULL_STRING="null";
	
    private static Pattern SYM_PATTERN=Pattern.compile("[\\\\/';]");
	
	private static Pattern STR_PATTERN=Pattern.compile("-{2}");
		
	/**
	 * Removes symbols <b>[\] [;] ['] [--]</b> in the str.
	 * 
	 * @param string need to filter
	 * @return filtered string
	 */
	public static String filterSql(String str){
		if(str==null){
			return null;
		}
		String result=SYM_PATTERN.matcher(str).replaceAll(StringUtils.EMPTY);
		result=STR_PATTERN.matcher(result).replaceAll(StringUtils.EMPTY);
		return result;
	}
	
	/**
	 * Replace the first character found in the original string with a new string.
	 *  <p>
     * Examples:
     * <blockquote><pre>
     * StringUtils.replaceFirst("? is here",'?',"John")
     *       returns "John is here"
     *       
     * StringUtils.replaceFirst("? is here",'?',null)
     *       returns "null is here"
     * 
     * </pre></blockquote>
	 * @param original string
	 * @param ch you need to replace
	 * @param newStr the new string you want to replace with
	 * @return
	 */
	public static String replaceFirst(String original,char ch,String newStr){
        if(original==null){
        	return null;
        }
        String newStrCopy=newStr;
        if(newStr==null){
        	newStrCopy=NULL_STRING;
        }
        char[] oriCharArray=original.toCharArray();
        int length=oriCharArray.length;
        int index=0;
        char[] result=null;
        boolean isCharExist=false;
        
        for(int i=0;i<length;i++){
        	if(oriCharArray[i]==ch){
        		index=i;
        		isCharExist=true;
        		break;
        	}
        }
        
        if(isCharExist){
        	int newStrLength=newStrCopy.length();
        	result=new char[length+newStrLength-1];
        	System.arraycopy(oriCharArray, 0, result, 0, index);
        	System.arraycopy(newStrCopy.toCharArray(), 0, result, index, newStrLength);
        	System.arraycopy(oriCharArray, index+1, result, index+newStrLength, length-index-1);
            return new String(result);
        }else{
        	return original;
        }     
	}
	
	/**
	 * Replace the oldStr in the pattern with a newStr.
	 *  <p>
     * Examples:
     * <blockquote><pre>
     * StringUtils.replaceFirst("@name is here","@name","John")
     *       returns "John is here"
     *       
     * StringUtils.replaceFirst("@name is here","@name",null)
     *       returns "null is here"
     * 
     * </pre></blockquote>
	 * @param pattern
	 * @param oldStr
	 * @param newStr
	 * @return
	 */
	public static String replaceFirst(String pattern, String oldStr,String newStr){
		if(pattern==null || oldStr==null){
			return pattern;
		}
		String newStrCopy=newStr;
		if(newStr==null){
			newStrCopy=NULL_STRING;
		}
		Pattern ptn=Pattern.compile(oldStr);
		return ptn.matcher(pattern).replaceFirst(newStrCopy);	
	}
	
	/**
	 * Returns a new string resulting from replacing all occurrences of ch in this string with values. <br>
	 * The string in values matches the ch in sequence.
	 *  <p>
     * Examples:
     * <blockquote><pre>
     * StringUtils.replaceAll("? and ? are here",'?',new String[]{"John"})
     *       returns "John and ? are here"
     *       
     * StringUtils.replaceAll("? and ? are here",'?',new String[]{"John","Tim"})
     *       returns "John and Tim are here"
     * 
     * </pre></blockquote>
	 * @param pattern
	 * @param ch
	 * @param values
	 * @return
	 */
	public static String replaceAll(String pattern,char ch,String[] values){
		if(pattern==null || values==null){
			return pattern;
		}
		int i=0;
		int[] indexes=charIndexes(pattern,ch);
		String[] valuesCopy=new String[indexes.length];
		System.arraycopy(values, 0, valuesCopy, 0, Math.min(valuesCopy.length, values.length));
		
		int chLength=pattern.length();
		for(i=0;i<valuesCopy.length;i++){
			if(valuesCopy[i]!=null){
				chLength+=valuesCopy[i].length()-1;
			}else{
				valuesCopy[i]=String.valueOf(ch);
			}
		}
		
		StringBuffer sb=new StringBuffer(chLength);
		int start=0;
		int end=0;
		for(i=0;i<valuesCopy.length;i++){
			end=indexes[i];
			sb.append(pattern.substring(start, end));
			sb.append(valuesCopy[i]);
			start=end+1;
		}
		if(start<pattern.length()){
			sb.append(pattern.substring(start));
		}
		return sb.toString();
	}
	
	/**
	 * Returns all the indexes of the ch in str.
	 *  <p>
     * Examples:
     * <blockquote><pre>
     * StringUtils.charIndexs("? and ? are here",'?')
     *       returns [0,6]
     * </pre></blockquote>
	 * 
	 * @param str
	 * @param ch
	 * @return
	 */
	public static int[] charIndexes(String str,char ch){
		if(str==null){
			return null;
		}
		char[] chs=str.toCharArray();
		List list=new ArrayList();
		for(int i=0;i<chs.length;i++){
			if(chs[i]==ch){
				list.add(new Integer(i));
			}
		}
		
		int[] result;
		if(list.isEmpty()){
			result=new int[0];
		}else{
			result=new int[list.size()];
		}
		
		for(int i=0;i<result.length;i++){
			result[i]=((Integer)list.get(i)).intValue();
		}
		return result;
	}
	
    private StringUtils (){
		
	}
}
